summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiam <byteslice@airmail.cc>2024-02-20 06:46:35 +0100
committerLiam <byteslice@airmail.cc>2024-02-21 04:15:37 +0100
commit62083fcafd11348e01cf0d99e2693cb608cca71b (patch)
treeeca4183bdc0d8b299c7ffdfa879d4e1acaffb773
parentaudio: move IFinalOutputRecorderManager{,ForApplet} (diff)
downloadyuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar.gz
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar.bz2
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar.lz
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar.xz
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.tar.zst
yuzu-62083fcafd11348e01cf0d99e2693cb608cca71b.zip
-rw-r--r--src/core/CMakeLists.txt12
-rw-r--r--src/core/hle/service/audio/audio.cpp5
-rw-r--r--src/core/hle/service/audio/audio_device.cpp183
-rw-r--r--src/core/hle/service/audio/audio_device.h35
-rw-r--r--src/core/hle/service/audio/audio_renderer.cpp210
-rw-r--r--src/core/hle/service/audio/audio_renderer.h45
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.cpp143
-rw-r--r--src/core/hle/service/audio/audio_renderer_manager.h (renamed from src/core/hle/service/audio/audren_u.h)7
-rw-r--r--src/core/hle/service/audio/audren_u.cpp552
9 files changed, 630 insertions, 562 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 68b940af3..5a1fc83bd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -489,6 +489,10 @@ add_library(core STATIC
hle/service/apm/apm_controller.h
hle/service/apm/apm_interface.cpp
hle/service/apm/apm_interface.h
+ hle/service/audio/audio_controller.cpp
+ hle/service/audio/audio_controller.h
+ hle/service/audio/audio_device.cpp
+ hle/service/audio/audio_device.h
hle/service/audio/audio_in_manager.cpp
hle/service/audio/audio_in_manager.h
hle/service/audio/audio_in.cpp
@@ -497,12 +501,12 @@ add_library(core STATIC
hle/service/audio/audio_out_manager.h
hle/service/audio/audio_out.cpp
hle/service/audio/audio_out.h
+ hle/service/audio/audio_renderer_manager.cpp
+ hle/service/audio/audio_renderer_manager.h
+ hle/service/audio/audio_renderer.cpp
+ hle/service/audio/audio_renderer.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
- hle/service/audio/audio_controller.cpp
- hle/service/audio/audio_controller.h
- hle/service/audio/audren_u.cpp
- hle/service/audio/audren_u.h
hle/service/audio/errors.h
hle/service/audio/final_output_recorder_manager_for_applet.cpp
hle/service/audio/final_output_recorder_manager_for_applet.h
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 02773aee5..82a2ae283 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -6,7 +6,7 @@
#include "core/hle/service/audio/audio_controller.h"
#include "core/hle/service/audio/audio_in_manager.h"
#include "core/hle/service/audio/audio_out_manager.h"
-#include "core/hle/service/audio/audren_u.h"
+#include "core/hle/service/audio/audio_renderer_manager.h"
#include "core/hle/service/audio/final_output_recorder_manager.h"
#include "core/hle/service/audio/final_output_recorder_manager_for_applet.h"
#include "core/hle/service/audio/hwopus.h"
@@ -25,7 +25,8 @@ void LoopProcess(Core::System& system) {
"audrec:a", std::make_shared<IFinalOutputRecorderManagerForApplet>(system));
server_manager->RegisterNamedService("audrec:u",
std::make_shared<IFinalOutputRecorderManager>(system));
- server_manager->RegisterNamedService("audren:u", std::make_shared<AudRenU>(system));
+ server_manager->RegisterNamedService("audren:u",
+ std::make_shared<IAudioRendererManager>(system));
server_manager->RegisterNamedService("hwopus", std::make_shared<HwOpus>(system));
ServerManager::RunServer(std::move(server_manager));
}
diff --git a/src/core/hle/service/audio/audio_device.cpp b/src/core/hle/service/audio/audio_device.cpp
new file mode 100644
index 000000000..3608d08c7
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.cpp
@@ -0,0 +1,183 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/audio_core.h"
+#include "common/string_util.h"
+#include "core/hle/service/audio/audio_device.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+using namespace AudioCore::Renderer;
+
+IAudioDevice::IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
+ u32 device_num)
+ : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
+ impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
+ event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
+ static const FunctionInfo functions[] = {
+ {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
+ {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
+ {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
+ {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
+ {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
+ {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
+ {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
+ {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
+ {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
+ {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
+ {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
+ {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
+ {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
+ {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
+ };
+ RegisterHandlers(functions);
+
+ event->Signal();
+}
+
+IAudioDevice::~IAudioDevice() {
+ service_context.CloseEvent(event);
+}
+
+void IAudioDevice::ListAudioDeviceName(HLERequestContext& ctx) {
+ const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
+
+ std::vector<AudioDevice::AudioDeviceName> out_names{};
+
+ const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
+
+ std::string out{};
+ for (u32 i = 0; i < out_count; i++) {
+ std::string a{};
+ u32 j = 0;
+ while (out_names[i].name[j] != '\0') {
+ a += out_names[i].name[j];
+ j++;
+ }
+ out += "\n\t" + a;
+ }
+
+ LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+
+ ctx.WriteBuffer(out_names);
+
+ rb.Push(ResultSuccess);
+ rb.Push(out_count);
+}
+
+void IAudioDevice::SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const f32 volume = rp.Pop<f32>();
+
+ const auto device_name_buffer = ctx.ReadBuffer();
+ const std::string name = Common::StringFromBuffer(device_name_buffer);
+
+ LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
+
+ if (name == "AudioTvOutput") {
+ impl->SetDeviceVolumes(volume);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioDevice::GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
+ const auto device_name_buffer = ctx.ReadBuffer();
+ const std::string name = Common::StringFromBuffer(device_name_buffer);
+
+ LOG_DEBUG(Service_Audio, "called. Name={}", name);
+
+ f32 volume{1.0f};
+ if (name == "AudioTvOutput") {
+ volume = impl->GetDeviceVolume(name);
+ }
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(volume);
+}
+
+void IAudioDevice::GetActiveAudioDeviceName(HLERequestContext& ctx) {
+ const auto write_size = ctx.GetWriteBufferSize();
+ std::string out_name{"AudioTvOutput"};
+
+ LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
+
+ out_name.resize(write_size);
+
+ ctx.WriteBuffer(out_name);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioDevice::QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "(STUBBED) called");
+
+ event->Signal();
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::GetActiveChannelCount(HLERequestContext& ctx) {
+ const auto& sink{system.AudioCore().GetOutputSink()};
+ u32 channel_count{sink.GetSystemChannels()};
+
+ LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+
+ rb.Push(ResultSuccess);
+ rb.Push<u32>(channel_count);
+}
+
+void IAudioDevice::QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(event->GetReadableEvent());
+}
+
+void IAudioDevice::ListAudioOutputDeviceName(HLERequestContext& ctx) {
+ const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
+
+ std::vector<AudioDevice::AudioDeviceName> out_names{};
+
+ const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
+
+ std::string out{};
+ for (u32 i = 0; i < out_count; i++) {
+ std::string a{};
+ u32 j = 0;
+ while (out_names[i].name[j] != '\0') {
+ a += out_names[i].name[j];
+ j++;
+ }
+ out += "\n\t" + a;
+ }
+
+ LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+
+ ctx.WriteBuffer(out_names);
+
+ rb.Push(ResultSuccess);
+ rb.Push(out_count);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_device.h b/src/core/hle/service/audio/audio_device.h
new file mode 100644
index 000000000..850c60051
--- /dev/null
+++ b/src/core/hle/service/audio/audio_device.h
@@ -0,0 +1,35 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/renderer/audio_device.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioDevice final : public ServiceFramework<IAudioDevice> {
+
+public:
+ explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
+ u32 device_num);
+ ~IAudioDevice() override;
+
+private:
+ void ListAudioDeviceName(HLERequestContext& ctx);
+ void SetAudioDeviceOutputVolume(HLERequestContext& ctx);
+ void GetAudioDeviceOutputVolume(HLERequestContext& ctx);
+ void GetActiveAudioDeviceName(HLERequestContext& ctx);
+ void QueryAudioDeviceSystemEvent(HLERequestContext& ctx);
+ void GetActiveChannelCount(HLERequestContext& ctx);
+ void QueryAudioDeviceInputEvent(HLERequestContext& ctx);
+ void QueryAudioDeviceOutputEvent(HLERequestContext& ctx);
+ void ListAudioOutputDeviceName(HLERequestContext& ctx);
+
+ KernelHelpers::ServiceContext service_context;
+ std::unique_ptr<AudioCore::Renderer::AudioDevice> impl;
+ Kernel::KEvent* event;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer.cpp b/src/core/hle/service/audio/audio_renderer.cpp
new file mode 100644
index 000000000..68415eb8f
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.cpp
@@ -0,0 +1,210 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "core/hle/service/audio/audio_renderer.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+using namespace AudioCore::Renderer;
+
+IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
+ AudioCore::AudioRendererParameterInternal& params,
+ Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
+ u32 process_handle, Kernel::KProcess& process_,
+ u64 applet_resource_user_id, s32 session_id)
+ : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
+ rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
+ impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
+ {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
+ {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
+ {3, &IAudioRenderer::GetState, "GetState"},
+ {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
+ {5, &IAudioRenderer::Start, "Start"},
+ {6, &IAudioRenderer::Stop, "Stop"},
+ {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
+ {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
+ {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
+ {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
+ {11, nullptr, "ExecuteAudioRendererRendering"},
+ {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
+ {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
+ };
+ // clang-format on
+ RegisterHandlers(functions);
+
+ process.Open();
+ impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
+ applet_resource_user_id, session_id);
+}
+
+IAudioRenderer::~IAudioRenderer() {
+ impl->Finalize();
+ service_context.CloseEvent(rendered_event);
+ process.Close();
+}
+
+void IAudioRenderer::GetSampleRate(HLERequestContext& ctx) {
+ const auto sample_rate{impl->GetSystem().GetSampleRate()};
+
+ LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(sample_rate);
+}
+
+void IAudioRenderer::GetSampleCount(HLERequestContext& ctx) {
+ const auto sample_count{impl->GetSystem().GetSampleCount()};
+
+ LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(sample_count);
+}
+
+void IAudioRenderer::GetState(HLERequestContext& ctx) {
+ const u32 state{!impl->GetSystem().IsActive()};
+
+ LOG_DEBUG(Service_Audio, "called, state {}", state);
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(state);
+}
+
+void IAudioRenderer::GetMixBufferCount(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(buffer_count);
+}
+
+void IAudioRenderer::RequestUpdate(HLERequestContext& ctx) {
+ LOG_TRACE(Service_Audio, "called");
+
+ const auto input{ctx.ReadBuffer(0)};
+
+ // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
+ // checking size 0. Performance size is 0 for most games.
+
+ auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
+ if (is_buffer_b) {
+ const auto buffersB{ctx.BufferDescriptorB()};
+ output_buffer.resize_destructive(buffersB[0].Size());
+ performance_buffer.resize_destructive(buffersB[1].Size());
+ } else {
+ const auto buffersC{ctx.BufferDescriptorC()};
+ output_buffer.resize_destructive(buffersC[0].Size());
+ performance_buffer.resize_destructive(buffersC[1].Size());
+ }
+
+ auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
+
+ if (result.IsSuccess()) {
+ if (is_buffer_b) {
+ ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
+ ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
+ } else {
+ ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
+ ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
+ }
+ } else {
+ LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(result);
+}
+
+void IAudioRenderer::Start(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ impl->Start();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::Stop(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ impl->Stop();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::QuerySystemEvent(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(Audio::ResultNotSupported);
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(ResultSuccess);
+ rb.PushCopyObjects(rendered_event->GetReadableEvent());
+}
+
+void IAudioRenderer::SetRenderingTimeLimit(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ IPC::RequestParser rp{ctx};
+ auto limit = rp.PopRaw<u32>();
+
+ auto& system_ = impl->GetSystem();
+ system_.SetRenderingTimeLimit(limit);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::GetRenderingTimeLimit(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ auto& system_ = impl->GetSystem();
+ auto time = system_.GetRenderingTimeLimit();
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(time);
+}
+
+void IAudioRenderer::ExecuteAudioRendererRendering(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+}
+
+void IAudioRenderer::SetVoiceDropParameter(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ IPC::RequestParser rp{ctx};
+ auto voice_drop_param{rp.Pop<f32>()};
+
+ auto& system_ = impl->GetSystem();
+ system_.SetVoiceDropParameter(voice_drop_param);
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultSuccess);
+}
+
+void IAudioRenderer::GetVoiceDropParameter(HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+
+ auto& system_ = impl->GetSystem();
+ auto voice_drop_param{system_.GetVoiceDropParameter()};
+
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(ResultSuccess);
+ rb.Push(voice_drop_param);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer.h b/src/core/hle/service/audio/audio_renderer.h
new file mode 100644
index 000000000..f8c48154b
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer.h
@@ -0,0 +1,45 @@
+// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include "audio_core/renderer/audio_renderer.h"
+#include "core/hle/service/kernel_helpers.h"
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
+public:
+ explicit IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
+ AudioCore::AudioRendererParameterInternal& params,
+ Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
+ u32 process_handle, Kernel::KProcess& process_,
+ u64 applet_resource_user_id, s32 session_id);
+ ~IAudioRenderer() override;
+
+private:
+ void GetSampleRate(HLERequestContext& ctx);
+ void GetSampleCount(HLERequestContext& ctx);
+ void GetState(HLERequestContext& ctx);
+ void GetMixBufferCount(HLERequestContext& ctx);
+ void RequestUpdate(HLERequestContext& ctx);
+ void Start(HLERequestContext& ctx);
+ void Stop(HLERequestContext& ctx);
+ void QuerySystemEvent(HLERequestContext& ctx);
+ void SetRenderingTimeLimit(HLERequestContext& ctx);
+ void GetRenderingTimeLimit(HLERequestContext& ctx);
+ void ExecuteAudioRendererRendering(HLERequestContext& ctx);
+ void SetVoiceDropParameter(HLERequestContext& ctx);
+ void GetVoiceDropParameter(HLERequestContext& ctx);
+
+ KernelHelpers::ServiceContext service_context;
+ Kernel::KEvent* rendered_event;
+ AudioCore::Renderer::Manager& manager;
+ std::unique_ptr<AudioCore::Renderer::Renderer> impl;
+ Kernel::KProcess& process;
+ Common::ScratchBuffer<u8> output_buffer;
+ Common::ScratchBuffer<u8> performance_buffer;
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio_renderer_manager.cpp b/src/core/hle/service/audio/audio_renderer_manager.cpp
new file mode 100644
index 000000000..7baa9d8cf
--- /dev/null
+++ b/src/core/hle/service/audio/audio_renderer_manager.cpp
@@ -0,0 +1,143 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "audio_core/audio_render_manager.h"
+#include "audio_core/common/feature_support.h"
+#include "core/hle/kernel/k_process.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/service/audio/audio_device.h"
+#include "core/hle/service/audio/audio_renderer.h"
+#include "core/hle/service/audio/audio_renderer_manager.h"
+#include "core/hle/service/ipc_helpers.h"
+
+namespace Service::Audio {
+
+using namespace AudioCore::Renderer;
+
+IAudioRendererManager::IAudioRendererManager(Core::System& system_)
+ : ServiceFramework{system_, "audren:u"}, service_context{system_, "audren:u"},
+ impl{std::make_unique<Manager>(system_)} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &IAudioRendererManager::OpenAudioRenderer, "OpenAudioRenderer"},
+ {1, &IAudioRendererManager::GetWorkBufferSize, "GetWorkBufferSize"},
+ {2, &IAudioRendererManager::GetAudioDeviceService, "GetAudioDeviceService"},
+ {3, nullptr, "OpenAudioRendererForManualExecution"},
+ {4, &IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IAudioRendererManager::~IAudioRendererManager() = default;
+
+void IAudioRendererManager::OpenAudioRenderer(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ AudioCore::AudioRendererParameterInternal params;
+ rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
+ rp.Skip(1, false);
+ auto transfer_memory_size = rp.Pop<u64>();
+ auto applet_resource_user_id = rp.Pop<u64>();
+ auto transfer_memory_handle = ctx.GetCopyHandle(0);
+ auto process_handle = ctx.GetCopyHandle(1);
+
+ if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
+ LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(Audio::ResultOutOfSessions);
+ return;
+ }
+
+ auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
+ auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
+
+ const auto session_id{impl->GetSessionId()};
+ if (session_id == -1) {
+ LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(Audio::ResultOutOfSessions);
+ return;
+ }
+
+ LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
+ impl->GetSessionCount());
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
+ transfer_memory_size, process_handle, *process,
+ applet_resource_user_id, session_id);
+}
+
+void IAudioRendererManager::GetWorkBufferSize(HLERequestContext& ctx) {
+ AudioCore::AudioRendererParameterInternal params;
+
+ IPC::RequestParser rp{ctx};
+ rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
+
+ u64 size{0};
+ auto result = impl->GetWorkBufferSize(params, size);
+
+ std::string output_info{};
+ output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
+ output_info +=
+ fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
+ output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
+ static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
+ output_info += fmt::format(
+ "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
+ "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
+ "Context {:04X}",
+ params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
+ params.splitter_destinations, params.voices, params.perf_frames,
+ params.external_context_size);
+
+ LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
+ output_info, size);
+
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(result);
+ rb.Push<u64>(size);
+}
+
+void IAudioRendererManager::GetAudioDeviceService(HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+
+ const auto applet_resource_user_id = rp.Pop<u64>();
+
+ LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
+ ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
+}
+
+void IAudioRendererManager::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
+ LOG_ERROR(Service_Audio, "called. Implement me!");
+}
+
+void IAudioRendererManager::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
+ struct Parameters {
+ u32 revision;
+ u64 applet_resource_user_id;
+ };
+
+ IPC::RequestParser rp{ctx};
+
+ const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
+
+ LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
+ AudioCore::GetRevisionNum(revision), applet_resource_user_id);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
+ num_audio_devices++);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audio_renderer_manager.h
index 3d7993a16..3623f91c6 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audio_renderer_manager.h
@@ -4,7 +4,6 @@
#pragma once
#include "audio_core/audio_render_manager.h"
-#include "common/scratch_buffer.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/service.h"
@@ -15,10 +14,10 @@ class System;
namespace Service::Audio {
class IAudioRenderer;
-class AudRenU final : public ServiceFramework<AudRenU> {
+class IAudioRendererManager final : public ServiceFramework<IAudioRendererManager> {
public:
- explicit AudRenU(Core::System& system_);
- ~AudRenU() override;
+ explicit IAudioRendererManager(Core::System& system_);
+ ~IAudioRendererManager() override;
private:
void OpenAudioRenderer(HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
deleted file mode 100644
index 10108abc0..000000000
--- a/src/core/hle/service/audio/audren_u.cpp
+++ /dev/null
@@ -1,552 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include <array>
-#include <memory>
-
-#include "audio_core/audio_core.h"
-#include "audio_core/common/audio_renderer_parameter.h"
-#include "audio_core/common/feature_support.h"
-#include "audio_core/renderer/audio_device.h"
-#include "audio_core/renderer/audio_renderer.h"
-#include "audio_core/renderer/voice/voice_info.h"
-#include "common/alignment.h"
-#include "common/bit_util.h"
-#include "common/common_funcs.h"
-#include "common/logging/log.h"
-#include "common/polyfill_ranges.h"
-#include "common/scratch_buffer.h"
-#include "common/string_util.h"
-#include "core/core.h"
-#include "core/hle/kernel/k_event.h"
-#include "core/hle/kernel/k_process.h"
-#include "core/hle/kernel/k_transfer_memory.h"
-#include "core/hle/service/audio/audren_u.h"
-#include "core/hle/service/audio/errors.h"
-#include "core/hle/service/ipc_helpers.h"
-#include "core/memory.h"
-
-using namespace AudioCore::Renderer;
-
-namespace Service::Audio {
-
-class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
-public:
- explicit IAudioRenderer(Core::System& system_, Manager& manager_,
- AudioCore::AudioRendererParameterInternal& params,
- Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
- u32 process_handle, Kernel::KProcess& process_,
- u64 applet_resource_user_id, s32 session_id)
- : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
- rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
- impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process{process_} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"},
- {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
- {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
- {3, &IAudioRenderer::GetState, "GetState"},
- {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"},
- {5, &IAudioRenderer::Start, "Start"},
- {6, &IAudioRenderer::Stop, "Stop"},
- {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
- {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
- {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
- {10, &IAudioRenderer::RequestUpdate, "RequestUpdateAuto"},
- {11, nullptr, "ExecuteAudioRendererRendering"},
- {12, &IAudioRenderer::SetVoiceDropParameter, "SetVoiceDropParameter"},
- {13, &IAudioRenderer::GetVoiceDropParameter, "GetVoiceDropParameter"},
- };
- // clang-format on
- RegisterHandlers(functions);
-
- process.Open();
- impl->Initialize(params, transfer_memory, transfer_memory_size, process_handle, process,
- applet_resource_user_id, session_id);
- }
-
- ~IAudioRenderer() override {
- impl->Finalize();
- service_context.CloseEvent(rendered_event);
- process.Close();
- }
-
-private:
- void GetSampleRate(HLERequestContext& ctx) {
- const auto sample_rate{impl->GetSystem().GetSampleRate()};
-
- LOG_DEBUG(Service_Audio, "called. Sample rate {}", sample_rate);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(sample_rate);
- }
-
- void GetSampleCount(HLERequestContext& ctx) {
- const auto sample_count{impl->GetSystem().GetSampleCount()};
-
- LOG_DEBUG(Service_Audio, "called. Sample count {}", sample_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(sample_count);
- }
-
- void GetState(HLERequestContext& ctx) {
- const u32 state{!impl->GetSystem().IsActive()};
-
- LOG_DEBUG(Service_Audio, "called, state {}", state);
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(state);
- }
-
- void GetMixBufferCount(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- const auto buffer_count{impl->GetSystem().GetMixBufferCount()};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(buffer_count);
- }
-
- void RequestUpdate(HLERequestContext& ctx) {
- LOG_TRACE(Service_Audio, "called");
-
- const auto input{ctx.ReadBuffer(0)};
-
- // These buffers are written manually to avoid an issue with WriteBuffer throwing errors for
- // checking size 0. Performance size is 0 for most games.
-
- auto is_buffer_b{ctx.BufferDescriptorB()[0].Size() != 0};
- if (is_buffer_b) {
- const auto buffersB{ctx.BufferDescriptorB()};
- output_buffer.resize_destructive(buffersB[0].Size());
- performance_buffer.resize_destructive(buffersB[1].Size());
- } else {
- const auto buffersC{ctx.BufferDescriptorC()};
- output_buffer.resize_destructive(buffersC[0].Size());
- performance_buffer.resize_destructive(buffersC[1].Size());
- }
-
- auto result = impl->RequestUpdate(input, performance_buffer, output_buffer);
-
- if (result.IsSuccess()) {
- if (is_buffer_b) {
- ctx.WriteBufferB(output_buffer.data(), output_buffer.size(), 0);
- ctx.WriteBufferB(performance_buffer.data(), performance_buffer.size(), 1);
- } else {
- ctx.WriteBufferC(output_buffer.data(), output_buffer.size(), 0);
- ctx.WriteBufferC(performance_buffer.data(), performance_buffer.size(), 1);
- }
- } else {
- LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!",
- result.GetDescription());
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(result);
- }
-
- void Start(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- impl->Start();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void Stop(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- impl->Stop();
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void QuerySystemEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- if (impl->GetSystem().GetExecutionMode() == AudioCore::ExecutionMode::Manual) {
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(Audio::ResultNotSupported);
- return;
- }
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(rendered_event->GetReadableEvent());
- }
-
- void SetRenderingTimeLimit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- IPC::RequestParser rp{ctx};
- auto limit = rp.PopRaw<u32>();
-
- auto& system_ = impl->GetSystem();
- system_.SetRenderingTimeLimit(limit);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetRenderingTimeLimit(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto& system_ = impl->GetSystem();
- auto time = system_.GetRenderingTimeLimit();
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(time);
- }
-
- void ExecuteAudioRendererRendering(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
- }
-
- void SetVoiceDropParameter(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- IPC::RequestParser rp{ctx};
- auto voice_drop_param{rp.Pop<f32>()};
-
- auto& system_ = impl->GetSystem();
- system_.SetVoiceDropParameter(voice_drop_param);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetVoiceDropParameter(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- auto& system_ = impl->GetSystem();
- auto voice_drop_param{system_.GetVoiceDropParameter()};
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(voice_drop_param);
- }
-
- KernelHelpers::ServiceContext service_context;
- Kernel::KEvent* rendered_event;
- Manager& manager;
- std::unique_ptr<Renderer> impl;
- Kernel::KProcess& process;
- Common::ScratchBuffer<u8> output_buffer;
- Common::ScratchBuffer<u8> performance_buffer;
-};
-
-class IAudioDevice final : public ServiceFramework<IAudioDevice> {
-
-public:
- explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision,
- u32 device_num)
- : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"},
- impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)},
- event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} {
- static const FunctionInfo functions[] = {
- {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
- {1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
- {2, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolume"},
- {3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
- {4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
- {5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
- {6, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceNameAuto"},
- {7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
- {8, &IAudioDevice::GetAudioDeviceOutputVolume, "GetAudioDeviceOutputVolumeAuto"},
- {10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
- {11, &IAudioDevice::QueryAudioDeviceInputEvent, "QueryAudioDeviceInputEvent"},
- {12, &IAudioDevice::QueryAudioDeviceOutputEvent, "QueryAudioDeviceOutputEvent"},
- {13, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioOutputDeviceName"},
- {14, &IAudioDevice::ListAudioOutputDeviceName, "ListAudioOutputDeviceName"},
- };
- RegisterHandlers(functions);
-
- event->Signal();
- }
-
- ~IAudioDevice() override {
- service_context.CloseEvent(event);
- }
-
-private:
- void ListAudioDeviceName(HLERequestContext& ctx) {
- const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
-
- std::vector<AudioDevice::AudioDeviceName> out_names{};
-
- const u32 out_count = impl->ListAudioDeviceName(out_names, in_count);
-
- std::string out{};
- for (u32 i = 0; i < out_count; i++) {
- std::string a{};
- u32 j = 0;
- while (out_names[i].name[j] != '\0') {
- a += out_names[i].name[j];
- j++;
- }
- out += "\n\t" + a;
- }
-
- LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
-
- IPC::ResponseBuilder rb{ctx, 3};
-
- ctx.WriteBuffer(out_names);
-
- rb.Push(ResultSuccess);
- rb.Push(out_count);
- }
-
- void SetAudioDeviceOutputVolume(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- const f32 volume = rp.Pop<f32>();
-
- const auto device_name_buffer = ctx.ReadBuffer();
- const std::string name = Common::StringFromBuffer(device_name_buffer);
-
- LOG_DEBUG(Service_Audio, "called. name={}, volume={}", name, volume);
-
- if (name == "AudioTvOutput") {
- impl->SetDeviceVolumes(volume);
- }
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void GetAudioDeviceOutputVolume(HLERequestContext& ctx) {
- const auto device_name_buffer = ctx.ReadBuffer();
- const std::string name = Common::StringFromBuffer(device_name_buffer);
-
- LOG_DEBUG(Service_Audio, "called. Name={}", name);
-
- f32 volume{1.0f};
- if (name == "AudioTvOutput") {
- volume = impl->GetDeviceVolume(name);
- }
-
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(ResultSuccess);
- rb.Push(volume);
- }
-
- void GetActiveAudioDeviceName(HLERequestContext& ctx) {
- const auto write_size = ctx.GetWriteBufferSize();
- std::string out_name{"AudioTvOutput"};
-
- LOG_DEBUG(Service_Audio, "(STUBBED) called. Name={}", out_name);
-
- out_name.resize(write_size);
-
- ctx.WriteBuffer(out_name);
-
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(ResultSuccess);
- }
-
- void QueryAudioDeviceSystemEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "(STUBBED) called");
-
- event->Signal();
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(event->GetReadableEvent());
- }
-
- void GetActiveChannelCount(HLERequestContext& ctx) {
- const auto& sink{system.AudioCore().GetOutputSink()};
- u32 channel_count{sink.GetSystemChannels()};
-
- LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
-
- IPC::ResponseBuilder rb{ctx, 3};
-
- rb.Push(ResultSuccess);
- rb.Push<u32>(channel_count);
- }
-
- void QueryAudioDeviceInputEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "(STUBBED) called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(event->GetReadableEvent());
- }
-
- void QueryAudioDeviceOutputEvent(HLERequestContext& ctx) {
- LOG_DEBUG(Service_Audio, "called");
-
- IPC::ResponseBuilder rb{ctx, 2, 1};
- rb.Push(ResultSuccess);
- rb.PushCopyObjects(event->GetReadableEvent());
- }
-
- void ListAudioOutputDeviceName(HLERequestContext& ctx) {
- const size_t in_count = ctx.GetWriteBufferNumElements<AudioDevice::AudioDeviceName>();
-
- std::vector<AudioDevice::AudioDeviceName> out_names{};
-
- const u32 out_count = impl->ListAudioOutputDeviceName(out_names, in_count);
-
- std::string out{};
- for (u32 i = 0; i < out_count; i++) {
- std::string a{};
- u32 j = 0;
- while (out_names[i].name[j] != '\0') {
- a += out_names[i].name[j];
- j++;
- }
- out += "\n\t" + a;
- }
-
- LOG_DEBUG(Service_Audio, "called.\nNames={}", out);
-
- IPC::ResponseBuilder rb{ctx, 3};
-
- ctx.WriteBuffer(out_names);
-
- rb.Push(ResultSuccess);
- rb.Push(out_count);
- }
-
- KernelHelpers::ServiceContext service_context;
- std::unique_ptr<AudioDevice> impl;
- Kernel::KEvent* event;
-};
-
-AudRenU::AudRenU(Core::System& system_)
- : ServiceFramework{system_, "audren:u"},
- service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} {
- // clang-format off
- static const FunctionInfo functions[] = {
- {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
- {1, &AudRenU::GetWorkBufferSize, "GetWorkBufferSize"},
- {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
- {3, nullptr, "OpenAudioRendererForManualExecution"},
- {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
- };
- // clang-format on
-
- RegisterHandlers(functions);
-}
-
-AudRenU::~AudRenU() = default;
-
-void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- AudioCore::AudioRendererParameterInternal params;
- rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
- rp.Skip(1, false);
- auto transfer_memory_size = rp.Pop<u64>();
- auto applet_resource_user_id = rp.Pop<u64>();
- auto transfer_memory_handle = ctx.GetCopyHandle(0);
- auto process_handle = ctx.GetCopyHandle(1);
-
- if (impl->GetSessionCount() + 1 > AudioCore::MaxRendererSessions) {
- LOG_ERROR(Service_Audio, "Too many AudioRenderer sessions open!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(Audio::ResultOutOfSessions);
- return;
- }
-
- auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle).GetPointerUnsafe()};
- auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)};
-
- const auto session_id{impl->GetSessionId()};
- if (session_id == -1) {
- LOG_ERROR(Service_Audio, "Tried to open a session that's already in use!");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(Audio::ResultOutOfSessions);
- return;
- }
-
- LOG_DEBUG(Service_Audio, "Opened new AudioRenderer session {} sessions open {}", session_id,
- impl->GetSessionCount());
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioRenderer>(system, *impl, params, transfer_memory.GetPointerUnsafe(),
- transfer_memory_size, process_handle, *process,
- applet_resource_user_id, session_id);
-}
-
-void AudRenU::GetWorkBufferSize(HLERequestContext& ctx) {
- AudioCore::AudioRendererParameterInternal params;
-
- IPC::RequestParser rp{ctx};
- rp.PopRaw<AudioCore::AudioRendererParameterInternal>(params);
-
- u64 size{0};
- auto result = impl->GetWorkBufferSize(params, size);
-
- std::string output_info{};
- output_info += fmt::format("\tRevision {}", AudioCore::GetRevisionNum(params.revision));
- output_info +=
- fmt::format("\n\tSample Rate {}, Sample Count {}", params.sample_rate, params.sample_count);
- output_info += fmt::format("\n\tExecution Mode {}, Voice Drop Enabled {}",
- static_cast<u32>(params.execution_mode), params.voice_drop_enabled);
- output_info += fmt::format(
- "\n\tSizes: Effects {:04X}, Mixes {:04X}, Sinks {:04X}, Submixes {:04X}, Splitter Infos "
- "{:04X}, Splitter Destinations {:04X}, Voices {:04X}, Performance Frames {:04X} External "
- "Context {:04X}",
- params.effects, params.mixes, params.sinks, params.sub_mixes, params.splitter_infos,
- params.splitter_destinations, params.voices, params.perf_frames,
- params.external_context_size);
-
- LOG_DEBUG(Service_Audio, "called.\nInput params:\n{}\nOutput params:\n\tWorkbuffer size {:08X}",
- output_info, size);
-
- IPC::ResponseBuilder rb{ctx, 4};
- rb.Push(result);
- rb.Push<u64>(size);
-}
-
-void AudRenU::GetAudioDeviceService(HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
- const auto applet_resource_user_id = rp.Pop<u64>();
-
- LOG_DEBUG(Service_Audio, "called. Applet resource id {}", applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id,
- ::Common::MakeMagic('R', 'E', 'V', '1'), num_audio_devices++);
-}
-
-void AudRenU::OpenAudioRendererForManualExecution(HLERequestContext& ctx) {
- LOG_ERROR(Service_Audio, "called. Implement me!");
-}
-
-void AudRenU::GetAudioDeviceServiceWithRevisionInfo(HLERequestContext& ctx) {
- struct Parameters {
- u32 revision;
- u64 applet_resource_user_id;
- };
-
- IPC::RequestParser rp{ctx};
-
- const auto [revision, applet_resource_user_id] = rp.PopRaw<Parameters>();
-
- LOG_DEBUG(Service_Audio, "called. Revision {} Applet resource id {}",
- AudioCore::GetRevisionNum(revision), applet_resource_user_id);
-
- IPC::ResponseBuilder rb{ctx, 2, 0, 1};
-
- rb.Push(ResultSuccess);
- rb.PushIpcInterface<IAudioDevice>(system, applet_resource_user_id, revision,
- num_audio_devices++);
-}
-
-} // namespace Service::Audio